package common.impl;

import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.UUID;

import javax.imageio.ImageIO;

import org.apache.commons.lang.StringUtils;

import magick.CompositeOperator;
import magick.DrawInfo;
import magick.ImageInfo;
import magick.MagickImage;
import magick.PixelPacket;

import common.interf.IFileHandle;
import common.interf.IImage;

public class ImageImpl implements IImage {
	private IFileHandle fileHandle;

	public IFileHandle getFileHandle() {
		return fileHandle;
	}

	public void setFileHandle(IFileHandle fileHandle) {
		this.fileHandle = fileHandle;
	}

	static {
		System.setProperty("jmagick.systemclassloader", "no");
	}

	private final String[] FileTypes = { "application/jpg",
			"application/x-jpg", "image",
	// "image/jp","image/jpe","image/jpeg","image/pipeg","image/pjpeg","image/vnd.seiftview-jpeg",
	// "image/x-xbitmap","image/x-portable-xbitmap",
	// "image/gif",
	// "image/png","image/x-png",
	};

	/**
	 * 缩放url图像
	 * 
	 * @param inPath
	 *            : 输入Url
	 * @param path
	 *            :输出路径
	 * @param width
	 *            : 图形宽
	 * @param height
	 *            : 图形高
	 * @param waterMark
	 *            : 第一个元素为 watermark路径，第二个元素为位置，1：左上，2：右上，3：左下，4：右下，默认为1
	 * @return 文件名
	 */
	public Object[] zoomImage(String inPath, String outPath, Integer width,
			Integer height, String... waterMark) throws Exception {
		Integer ow, oh, nw = 0, nh = 0, bw = 0, bh = 0;
		ImageInfo info = new ImageInfo(inPath);
		boolean addEdge = false;
		info.setQuality(70);
		MagickImage image = new MagickImage(info);
		ow = image.getDimension().width;
		oh = image.getDimension().height;
		if (ow == width && oh == height && waterMark == null)
			return null;

		if (width > 0 && height == 0) { // 按width 缩放
			height = (int) (Math.round(((double) width) / ow * oh));
		} else if (height > 0 && width == 0) { // 按height 缩放
			width = (int) (Math.round(((double) height) / oh * ow));
		}
		if (width == 0 && height == 0) {
			width = ow;
			height = oh;
		} else {
			float scaleOld = (float) ow / oh;
			float scaleNew = (float) width / height;
			// 5%范围内算宽高比一致,不加白边
			if (scaleOld > scaleNew * 1.05 || scaleOld < scaleNew * 0.95) { // 加白边
				if (scaleOld > scaleNew) {
					nw = width;
					nh = (int) (width / scaleOld);
					bh = (int) (height - nh) / 2;
				} else {
					nh = height;
					nw = (int) (height * scaleOld);
					bw = (int) (width - nw) / 2;
				}
				addEdge = true;
			} else {
				width = (int) (Math.round(width));
				height = (int) (Math.round(height));
			}
		}

		MagickImage small = null;
		if (addEdge) { // 添加白边
			small = image.scaleImage(nw, nh);
			small.setBorderColor(PixelPacket.queryColorDatabase("white"));
			small = small.borderImage(new Rectangle(0, 0, bw, bh));
		} else {
			small = image.scaleImage(width, height);
		}
		image.destroyImages();

		// 添加水印
		if (waterMark != null && waterMark.length > 0) {
			ImageInfo logo = new ImageInfo(waterMark[0]);
			MagickImage ilogo = new MagickImage(logo);
			// 确定水印位置
			int left = 2;
			int top = 2;
			if (waterMark.length > 1) {
				if ("2".endsWith(waterMark[1])) {
					left = width - ilogo.getDimension().width - 2;
				} else if ("3".endsWith(waterMark[1])) {
					top = height - ilogo.getDimension().height - 2;
				} else if ("4".endsWith(waterMark[1])) {
					left = width - ilogo.getDimension().width - 2;
					top = height - ilogo.getDimension().height - 2;
				}
			}
			if (left < 2)
				left = 2;
			if (top < 2)
				top = 2;
			small.compositeImage(CompositeOperator.AtopCompositeOp, ilogo,
					left, top);
			ilogo.destroyImages();
		}
		// 确定文件名
		String fn = null;
		File dir = new File(outPath);
		if (!dir.exists())
			dir.mkdirs();
		for (;;) {
			int index = inPath.lastIndexOf(".");
			String fileType = ".jpg";
			if (index > -1)
				fileType = inPath.substring(index);
			fn = UUID.randomUUID().toString().replaceAll("-", "") + fileType;
			File file = new File(outPath + "/" + fn);
			if (!file.exists())
				break;
		}
		small.setFileName(outPath + "/" + fn);
		small.writeImage(new ImageInfo());
		small.destroyImages();
		return new Object[] { fn, width, height };
	}

	/**
	 * 添加水印
	 * 
	 * @param src
	 *            :原图
	 * @param watermark
	 *            :水印
	 * @param left
	 *            :水印左坐标
	 * @param top
	 *            :水印y坐标
	 * @param opacity
	 *            透明度 0 - 100, 0 为不透明
	 */
	public void addWaterMark(String src, String watermark, Integer left,
			Integer top, String outFile) throws Exception {
		ImageInfo info = new ImageInfo(src);
		info.setQuality(70);
		MagickImage image = new MagickImage(info);

		ImageInfo logo = new ImageInfo(watermark);
		MagickImage ilogo = new MagickImage(logo);
		if (null == left)
			left = 0;
		if (null == top)
			top = 0;
		image.compositeImage(CompositeOperator.AtopCompositeOp, ilogo, left,
				top);
		image.setFileName(outFile);
		image.writeImage(new ImageInfo());
		image.destroyImages();
		ilogo.destroyImages();
	}

	public String addTextMark(String src, String text, Integer left,
			Integer top, String outPath) throws Exception {
		ImageInfo info = new ImageInfo(src);
		info.setQuality(70);
		MagickImage image = new MagickImage(info);

		DrawInfo aInfo = new DrawInfo(info);
		aInfo.setFill(PixelPacket.queryColorDatabase("black"));
		aInfo.setUnderColor(new PixelPacket(255, 255, 255, 0));
		aInfo.setPointsize(26);
		aInfo.setTextAntialias(true);
		aInfo.setOpacity(0);
		aInfo.setText(text);
		aInfo.setGeometry("+" + left + "+" + top);
		image.annotateImage(aInfo);
		String fn = null;
		File dir = new File(outPath);
		if (!dir.exists())
			dir.mkdirs();
		for (;;) {
			fn = UUID.randomUUID().toString().replaceAll("-", "") + ".png";
			File file = new File(outPath + "/" + fn);
			if (!file.exists())
				break;
		}
		image.setFileName(outPath + "/" + fn);
		image.writeImage(new ImageInfo());
		image.destroyImages();
		return fn;
	}

	/********************* 检查图片 ********************/
	/**
	 * 检查图片
	 * 
	 * @param image
	 *            :图像
	 * @param width
	 *            :图片宽度
	 * @param height
	 *            :图片高度
	 * @return
	 */
	public boolean checkImage(BufferedImage img, Integer width, Integer height) {
		if (width > 0) {
			if (img.getWidth() != width)
				return false;
		}
		if (height > 0) {
			if (img.getHeight() != height)
				return false;
		}
		return true;
	}

	/**
	 * 检查图片
	 * 
	 * @param inPath
	 *            图片路径
	 * @param width
	 *            :图片宽度
	 * @param height
	 *            :图片高度
	 * @return
	 */
	public boolean checkImage(String inPath, Integer width, Integer height)
			throws Exception {
		Integer ow;
		ImageInfo info = new ImageInfo(inPath);
		info.setQuality(70);
		MagickImage image = new MagickImage(info);
		ow = image.getDimension().width;
		if (ow > width) {
			return true;
		}
		return false;
	}

	/**
	 * 检查图片
	 * 
	 * @param file
	 *            :图像文件
	 * @param fileType
	 *            :要验证的文件类型
	 * @param size
	 *            :文件大小
	 * @param width
	 *            :图片宽度
	 * @param height
	 *            :图片高度
	 * @return
	 */
	public boolean checkImage(File file, Integer size, Integer width,
			Integer height) {
		boolean flag1 = false;
		boolean flag2 = true;
		String fileType = null;
		if (!file.exists())
			return false;
		try {
			fileType = fileHandle.getFileType(file);
		} catch (Exception e) {
			fileType = "";
		}

		for (String ft : FileTypes) {
			if (fileType.contains(ft)) {
				flag1 = true;
				break;
			}
		}
		if (size > 0) {
			if (file.length() > size)
				return false;
		}
		if (width > 0 && height > 0) {
			try {
				BufferedImage img = ImageIO.read(file);
				flag2 = checkImage(img, width, height);
			} catch (IOException e) {

			}
		}
		return flag1 && flag2;
	}

	public int[] getWH(String imageUrl) throws Exception {
		int[] o = new int[2];
		ImageInfo info = new ImageInfo(imageUrl);
		MagickImage image = new MagickImage(info);
		o[0] = image.getDimension().width;
		o[1] = image.getDimension().height;
		return o;
	}

	public static String addWaterMark(File baseFile, File waterMarkFile, int x,
			int y, int w, int h, String filePath,String fileName) throws Exception {
		if (null == baseFile || null == waterMarkFile)
			return null;
		if (!baseFile.exists() || !waterMarkFile.exists())
			return null;
		BufferedImage bi = ImageIO.read(baseFile);
		Graphics2D graphics2d = bi.createGraphics();
		Image wmImage = ImageIO.read(waterMarkFile);
		graphics2d.drawImage(wmImage, x, y, w, h, null);
		graphics2d.dispose();
		String uuid = UUID.randomUUID().toString().replaceAll("-", "");
		if(!StringUtils.isEmpty(fileName))
			uuid = fileName;
		FileOutputStream fos = null;
		try {
			File pathFile = new File(filePath);
			if (!pathFile.exists())
				pathFile.mkdirs();
			fos = new FileOutputStream(new File(filePath + "/" + uuid + ".jpg"));
			ImageIO.write(bi, "JPG", fos);
		} catch (Exception e) {
		} finally {
			if (null != fos)
				try {
					fos.close();
				} catch (Exception e2) {
				}
		}
		return uuid + ".jpg";
	}

}
